package com.example.springboot.web;

import com.example.springboot.mapper.TestMapper;
import com.google.gson.Gson;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Hashtable;

// 每次浏览器链接上来, 都会创建一个新的 TalkServer 对象, 坑
// 第一个对象 是Spring 创建的, 后面的都是 webSocket 创建的
// 因此,后面创建的对象, 没有注入 bean
@ServerEndpoint("/talk/{id}")
@Component
public class TalkServer {

    // 存放所有在线用户的集合
    static Hashtable<String,Session> sessions = new Hashtable<>();

    // Spring 不能对静态属性注入
    static TestMapper testMapper;

    // 使用实例set方法, 对静态属性注入
    @Resource
    public void setTestMapper(TestMapper testMapper) {
        TalkServer.testMapper = testMapper;
    }

    @OnOpen
    public void onOpen(@PathParam("id") String id, Session session){
        // 给当前用户发送已上线的用户信息
        sessions.values().forEach(s->{
            send(session, new Msg(
                    ""+s.getUserProperties().get("id"),
                    null,id,"上线了"));
        });

        // 查询用户信息   错误的用法
        // 明明已经注入, 但是任然为空
        testMapper.selectAllAccount();

        sessions.put(id, session);
        // 将 id 保存到会话
        session.getUserProperties().put("id",id);

        sessions.values().forEach(s->{
            send(s, new Msg(id,null,id,"上线了"));
        });
    }

    @OnClose
    public void onClose(Session session){
        String id = (String) session.getUserProperties().get("id");
        sessions.remove(id);
        sessions.values().forEach(s->{
            send(s, new Msg(null,id,id,"下线了"));
        });
    }

    // 接受到用户发送的消息 => 转发
    @OnMessage
    public void onMessage(String message, Session session){
        // 全部用户的群发
        sessions.values().forEach(s->{
            send(s, new Msg(null, null,
                    (String) session.getUserProperties().get("id"),
                    message));
        });


        // 私聊  TODO


        // 自定义群发  TODO
    }

    Gson gson = new Gson();
    // 给指定的客户端发送消息
    public void send(Session session, Object obj){
        String json = gson.toJson(obj);
        try {
            session.getBasicRemote().sendText(json);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

@Data
@NoArgsConstructor
@AllArgsConstructor
class Msg{
    String onlineUser; // 上线用户
    String downlineUser; // 下线用户
    String sendUser;     // 发送消息的用户
    String sendMsg;     // 发送的消息
}
